package com.analyst.service.impl;

import com.analyst.dto.ui.UpdatedGraphUI;
import com.analyst.entity.Job;
import com.analyst.dto.ui.EdgeUI;
import com.analyst.dto.ui.GraphDataUI;
import com.analyst.dto.ui.NodeUI;
import com.analyst.service.IGraphService;
import com.github.benmanes.caffeine.cache.Cache;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * ClassName: GraphService
 * Package: com.analyst.service.impl
 * Description:
 *
 * @Author wk
 * @Create 2023/08/8 0008 上午 10:08:48
 * @Version 1.0
 */
@Service
public class GraphService implements IGraphService {
    @Autowired
    private Cache<String, Map<String, Job>> jobcache;

    public UpdatedGraphUI getUpdatedGraphData(List<Set> nodesAndEdges, Map<String, Job> jobMap, String improveTimeForEndJob) {
        Set<NodeUI> nodes = nodesAndEdges.get(0);
        Set<EdgeUI> edges = nodesAndEdges.get(1);

//        nodes.stream()
//                .filter(node -> jobMap.containsKey(node.getId().split("\n")[0]) && jobMap.get(node.getId().split("\n")[0]).isHighLight())
//                .forEach(NodeUI::buildHighLight);
        nodes.stream()
                .filter(node -> jobMap.containsKey(node.getId().split("\n")[0]))
                .forEach(node -> {
                    Job job = jobMap.get(node.getId().split("\n")[0]);
                    if (job.getEndTime().getTime() - job.getBeginTime().getTime() > 60 * 60 * 1000 * 3 || job.getPendingTime() > 60 * 60 * 1000 * 1) {
                        node.buildRed();
                    }
                    if (job.isUpdate()) {
                        node.buildPurple();
                    }
                    if (job.isHighLight()) {
                        node.buildHighLight();
                    }
                });

        // Apply buildHighLight() method to edges where both source and target nodes are highLighted
        edges.stream()
                .filter(edge -> jobMap.containsKey(edge.getSource().split("\n")[0]) && jobMap.get(edge.getSource().split("\n")[0]).isHighLight()
                        && jobMap.containsKey(edge.getTarget().split("\n")[0]) && jobMap.get(edge.getTarget().split("\n")[0]).isHighLight())
                .forEach(EdgeUI::buildHighLight);

        return new UpdatedGraphUI(nodes, edges, improveTimeForEndJob);
    }

    @Override
    public UpdatedGraphUI getUpdatedGraphData(Job endJob, List<Set> nodesAndEdges, String improveTimeForEndJob) {
        Map<String, Job> cachedJobsMap = jobcache.getIfPresent(endJob.getId());
        UpdatedGraphUI result = new UpdatedGraphUI();
        if (cachedJobsMap != null) {
            result = getUpdatedGraphData(nodesAndEdges, cachedJobsMap, improveTimeForEndJob);
            jobcache.put(endJob.getId(), cachedJobsMap);
        }
        return result;
    }

    @Override
    public GraphDataUI getGraphData(Job endJob, List<Set> nodesAndEdges) {
        Map<String, Job> cachedJobsMap = jobcache.getIfPresent(endJob.getId());
        GraphDataUI result = new GraphDataUI();
        if (cachedJobsMap != null) {
            result = getGraphData(nodesAndEdges, cachedJobsMap);
            jobcache.put(endJob.getId(), cachedJobsMap);
        }
        return result;
    }
    public GraphDataUI getGraphData(List<Set> nodesAndEdges, Map<String, Job> jobMap) {
        Set<NodeUI> nodes = nodesAndEdges.get(0);
        Set<EdgeUI> edges = nodesAndEdges.get(1);

//        nodes.stream()
//                .filter(node -> jobMap.containsKey(node.getId().split("\n")[0]) && jobMap.get(node.getId().split("\n")[0]).isHighLight())
//                .forEach(NodeUI::buildHighLight);
        nodes.stream()
                .filter(node -> jobMap.containsKey(node.getId().split("\n")[0]))
                .forEach(node -> {
                    Job job = jobMap.get(node.getId().split("\n")[0]);
                    if (job.getEndTime().getTime() - job.getBeginTime().getTime() > 60 * 60 * 1000 * 3 || job.getPendingTime() > 60 * 60 * 1000 * 1) {
                        node.buildRed();
                    }
                    if (job.isUpdate()) {
                        node.buildPurple();
                    }
                    if (job.isHighLight()) {
                        node.buildHighLight();
                    }
                });

        // Apply buildHighLight() method to edges where both source and target nodes are highLighted
        edges.stream()
                .filter(edge -> jobMap.containsKey(edge.getSource().split("\n")[0]) && jobMap.get(edge.getSource().split("\n")[0]).isHighLight()
                        && jobMap.containsKey(edge.getTarget().split("\n")[0]) && jobMap.get(edge.getTarget().split("\n")[0]).isHighLight())
                .forEach(EdgeUI::buildHighLight);

        return new GraphDataUI(nodes, edges);
    }
}
